
Concentre.Factory.Events = {
	nativeEvents : {mouseover:1,mouseout:1,mousemove:1,mousedown:1,mouseup:1,click:1,change:1,focus:1,blur:1,load:1,unload:1,keypress:1,keyup:1,keydown:1,select:1,propertychange:1},
	extraEvents : {
		/**
		 * Xforms lifecycle events
		 * @see http://www.w3.org/TR/xforms/slice4.html
		 *
		 * @private
		 * @const
		 * @type Array
		 */
	  		'xforms-model-construct': ['Events',true, true] ,
	  		'xforms-model-construct-done': ['Events',true, true] ,
			'xforms-ready': ['Events',true, true],
			'xforms-model-destruct': ['Events',true, true],

		/**
		 * Xforms interaction events
		 * @see http://www.w3.org/TR/xforms/slice4.html#rpm-interaction
		 *
		 * @private
		 * @const
		 * @type Array
		 */
  			'xforms-next' :['Events',true, true],
  			'xforms-previous' :['Events',true, true],
  			'xforms-focus' :['Events',true, true],
  			'xforms-help' :['Events',true, true],
				'xforms-hint' :['Events',true, true],
				'xforms-refresh' :['Events',true, true],
				'xforms-revalidate' :['Events',true, true],
				'xforms-recalculate' :['Events',true, true],
				'xforms-rebuild' :['Events',true, true],
				'xforms-reset' :['Events',true, true],
				'xforms-submit' :['Events',true, true],
		/**
		 * Xforms notification events
		 * @see http://www.w3.org/TR/xforms/slice4.html#evt-notify
		 *
		 * @private
		 * @const
		 * @type Array
		 */
    		'DOMActivate' :['UIEvents',true, true],
    		'xforms-activate' :['Events',true, true],
    		'xforms-value-changed' :['Events',true, true],
    		'xforms-select' :['Events',true, true],
    		'xforms-deselect' :['Events',true, true],
    		'xforms-scroll-first' :['Events',true, true],
    		'xforms-scroll-last' :['Events',true, true],
    		'xforms-insert' :['Events',true, true],
    		'xforms-delete' :['Events',true, true],
    		'xforms-setindex' :['Events',true, true],
    		'xforms-valid' :['Events',true, true],
    		'xforms-invalid' :['Events',true, true],
        'DOMFocusIn' :['UIEvents',true, true],
        'DOMFocusOut' :['UIEvents',true, true],
        'xforms-readonly' :['Events',true, true],
        'xforms-readwrite' :['Events',true, true],
        'xforms-required' :['Events',true, true],
        'xforms-optional' :['Events',true, true],
        'xforms-enabled' :['Events',true, true],
        'xforms-disabled' :['Events',true, true],
        'xforms-in-range' :['Events',true, true],
        'xforms-out-of-range' :['Events',true, true],
        'xforms-submit-done' :['Events',true, true],
        'xforms-submit-error' :['Events',true, true],
        'xforms-submit-serialize' :['Events',true, true],
				'xforms-duplicate' :['Events',true, true],
				'xforms-destroy' :['Events',true, true],
				'xforms-close' :['Events',true, true],
				'xforms-output-error' :['Events',true, true],

		/**
		 * Xforms error indications events
		 * @see http://www.w3.org/TR/xforms/slice4.html#rpm-errors
		 *
		 * @private
		 * @const
		 * @type Array
		 */
	    	'xforms-binding-exception' :['Events',true, true],
	    	'xforms-link-exception' :['Events',true, true],
	    	'xforms-link-error'  :['Events',true, true],
	    	'xforms-compute-exception': ['Events',true, true],
	    	
	    	
	    	'xinclude-done': ['Events',true, true],
	    	'xinclude-error': ['Events',true, true]
	},

	listeners : [],
	previousFocalElement:null,
	currentFocalElement:null,

	initialize: function() {
	
	
		if (document.all) {
		
		var self = this;
		
		function findActiveElement() {
			var e = window.event;

		
			if (e.propertyName=='activeElement') {
			
				if (self.previousFocalElement) {
					self.fire(self.previousFocalElement, 'blur');
					
					if (self.previousValueElement != getValue(self.previousFocalElement)) {
						self.fire(self.previousFocalElement, 'change');
					}
				}
				
				if (self.currentFocalElement &&  document.activeElement) {
					self.previousFocalElement = document.activeElement;
					self.previousValueElement = getValue(document.activeElement);
				}
				
				self.currentFocalElement = document.activeElement;
				self.fire(document.activeElement, 'focus');
			
				
			}
			
		}
		
		document.attachEvent('onpropertychange', findActiveElement); 
		
		}
		
	},

	
	fix : function(event) {
		if (!event) event = window.event;

		if (event.target) {
			if (event.target.nodeType == 3) event.target = event.target.parentNode;
		} else if (event.srcElement) {
			event.target = event.srcElement;
		}

		return event;
	},

	fire : function (target, name, contextInfo) {
		var self = Concentre.Factory.Events;
		if (document.createEvent) {
			var xevt = self.extraEvents[name];
			assert (xevt,'Unknown event : '+name+ target.innerHTML);
			//concentre.factory.status.set('FireEvent: ' + name);
			
			var evt = document.createEvent(xevt[0]);
			switch(xevt[0]) {
				case 'UIEvents':
					evt.initUIEvent(name, xevt[1], xevt[2], window, 1);
					break;
				case 'Events':	
					evt.initEvent(name, xevt[1], xevt[2]);
					break;
			}			
			
			evt.contextInfo = contextInfo;
			target.dispatchEvent(evt);
		} else {
		
			
			for (var elt = target; elt!=null; elt=elt.parentNode)  {
				if (elt.nodeName=='HTML') break;
				if (elt._listeners) {
					for (var i in elt._listeners[name]) {
						elt._listeners[name][i]( {toto:'hola',type: name, target: target, currentTarget: elt} );
					}
				}
				
			}
		}
	},

	register : function(element, type, func) {	
		var s = Concentre.Factory.Events;
		s.listeners.push([element, type, func]);

		if (element.addEventListener) {
			element.addEventListener(type, func, true);
		} else if (element.attachEvent) {
			if (!element._listeners) element._listeners = new Array();
			if (!element._listeners[type]) element._listeners[type] = new Array();

			if (typeof func == "object" && typeof func.handleEvent == "function" ) {
				var workaroundFunc = function(evt) {
					if (!evt) evt = window.event;
					if (evt.srcElement) evt.target = evt.srcElement;
										
					var args = evt || {type: type, target:  window.event.srcElement, currentTarget: element}; 
					func.handleEvent.call(func, args);
				
					/*
					switch (evt.target.tagName) {
						case 'SELECT':
							switch(type) {
								case 'keyup':
									Concentre.Factory.Events.fire( evt.target, 'change');
									break;
								case 'click':
									if (evt.target
									Concentre.Factory.Events.fire( evt.target, 'change');
							}
				
							break;		
					}
					*/
					
					
					
				}					
			}	else {
				var workaroundFunc = function() {
				func.apply(element, new Array());
				}
			}			
			
			element._listeners[type][func] = workaroundFunc;
			element.attachEvent((Concentre.Factory.Events.nativeEvents[type]?'on':'')+ type, workaroundFunc);
			
		}
	},

	unregister : function(element, type, func) {
		if (element.removeEventListener) {
			element.removeEventListener(type, func, false);
		}
		 else if (element.detachEvent) {
			if (element._listeners && element._listeners[type] && element._listeners[type][func]) {
				element.detachEvent((concentre.factory.events.nativeEvents[type]?'on':'') + type, element._listeners[type][func]);
			}
		}
	},

	unregisterAll : function () {
		var s = concentre.factory.events;		
		for(var l in s.listeners) {
			s.unregister(l[0],l[1],l[2]);
		}
	},

	preventDefault : function (evt) {
		if (evt.preventDefault) {
			evt.preventDefault();
		} else {
			//window.event.cancelBubble = true;
		}
	},
	
	stopPropagation : function (evt) {
		if (evt.stopPropagation) {
			evt.stopPropagation();
		} else {
			window.event.cancelBubble = true;
		}
	}
};
